import { message } from 'antd';
import { request } from '@/utils/request';
import { getLocale, toApiLanguageCode, tt } from '@/utils/in18';

export type GenerationImage = {
  filename: string;
  subfolder?: string;
  type?: string;
  url: string;
};

export type GeneratedWork = {
  id: number;
  is_public: boolean;
  likes_count: number;
  is_liked?: boolean;
  views_count?: number;
  downloads_count?: number;
  used_as_template_count?: number;
  image_url?: string;
};

export type GenerationResultItem = {
  task_id: number;
  status: 'queued' | 'running' | 'succeeded' | 'failed' | string;
  images: GenerationImage[];
  output_work?: GeneratedWork;
};

export type GenerationState = {
  pendingTaskIds: number[];
  results: GenerationResultItem[];
};

const LS_PENDING_KEY = 'GEN_PENDING_TASK_IDS';
const LS_RESULTS_KEY = 'GEN_RESULTS';

function readPendingFromStorage(): number[] {
  try {
    const raw = localStorage.getItem(LS_PENDING_KEY);
    if (!raw) return [];
    const arr = JSON.parse(raw);
    return Array.isArray(arr) ? Array.from(new Set(arr.filter((x: any) => Number.isFinite(x)))) : [];
  } catch {
    return [];
  }
}

function writePendingToStorage(ids: number[]) {
  try { localStorage.setItem(LS_PENDING_KEY, JSON.stringify(Array.from(new Set(ids)))); } catch { }
}

function readResultsFromStorage(): GenerationResultItem[] {
  try {
    const raw = localStorage.getItem(LS_RESULTS_KEY);
    if (!raw) return [];
    const arr = JSON.parse(raw);
    if (!Array.isArray(arr)) return [];
    return arr.filter((x) => x && Number.isFinite(x.task_id));
  } catch {
    return [];
  }
}

function writeResultsToStorage(list: GenerationResultItem[]) {
  try { localStorage.setItem(LS_RESULTS_KEY, JSON.stringify(list)); } catch { }
}

let state: GenerationState = {
  pendingTaskIds: readPendingFromStorage(),
  results: readResultsFromStorage(),
};

type Listener = () => void;
const listeners = new Set<Listener>();

function notify() {
  listeners.forEach((fn) => {
    try { fn(); } catch { }
  });
  try { window.dispatchEvent(new CustomEvent('generation:state-changed')); } catch { }
}

function setState(next: Partial<GenerationState>) {
  state = { ...state, ...next };
  writePendingToStorage(state.pendingTaskIds);
  writeResultsToStorage(state.results);
  notify();
}

function addPending(taskId: number) {
  if (!Number.isFinite(taskId)) return;
  if (state.pendingTaskIds.includes(taskId)) return;
  setState({ pendingTaskIds: [...state.pendingTaskIds, taskId] });
}

function removePending(taskId: number) {
  if (!Number.isFinite(taskId)) return;
  if (!state.pendingTaskIds.includes(taskId)) return;
  setState({ pendingTaskIds: state.pendingTaskIds.filter((id) => id !== taskId) });
}

function upsertResult(item: GenerationResultItem) {
  const exists = state.results.findIndex((x) => x.task_id === item.task_id);
  if (exists >= 0) {
    const next = state.results.slice();
    next[exists] = item;
    setState({ results: next });
  } else {
    setState({ results: [item, ...state.results] });
  }
}

function updateResultWork(workId: number, partial: Partial<GeneratedWork>) {
  if (!Number.isFinite(workId)) return;
  const idx = state.results.findIndex((x) => Number(x?.output_work?.id) === Number(workId));
  if (idx < 0) return;
  const next = state.results.slice();
  const cur = next[idx];
  const curWork = cur?.output_work || undefined;
  next[idx] = {
    ...cur,
    output_work: curWork ? { ...curWork, ...partial } : curWork,
  } as GenerationResultItem;
  setState({ results: next });
}

export async function createGenerationTask(payload: {
  template_id: number;
  notify_channel: string;
  role_prompt: string;
  user_prompt: string;
  self_prompt?: string;
  is_public: boolean;
  language?: string;
  category?: string;
}): Promise<number | null> {
  try {
    const locale = getLocale();
    const lang = toApiLanguageCode(locale as any);
    // 调用创建生成任务接口
    const res = await request.post('/api/generation/createGenerationTaskRoute', {
      ...payload,
      // 保证 language 字段存在于请求体
      language: payload.language || lang,
    });
    if (res?.data?.success === true && Number.isFinite(res?.data?.task_id)) {
      const taskId = Number(res.data.task_id);
      addPending(taskId);
      return taskId;
    }
  } catch (e) {
    // ignore
  }
  return null;
}

export async function pollOnce() {
  // 先检查用户是否登录
  const UserData = localStorage.getItem('userData')
  if (!UserData) {
    return
  }

  const ids = state.pendingTaskIds;
  if (!ids || ids.length === 0) return;
  try {
    // 轮询获取任务结果
    const res = await request.post('/api/generation/getGenerationResultRoute', { task_id: ids });
    const results: GenerationResultItem[] = res?.data?.data?.results || [];
    if (!Array.isArray(results)) return;
    for (const item of results) {
      const taskId = Number(item?.task_id);
      if (!Number.isFinite(taskId)) continue;
      if (item.status === 'succeeded') {
        upsertResult({
          task_id: taskId,
          status: 'succeeded',
          images: Array.isArray(item.images) ? item.images : [],
          output_work: item && (item as any).output_work ? (item as any).output_work as GeneratedWork : undefined,
        });
        removePending(taskId);
        try { message.success(tt('CreatImg.new_work_generated_success')); } catch { }
      } else if (item.status === 'failed') {
        // 失败则移出 pending，但不入库（或可入库标记失败）
        removePending(taskId);
      } else {
        // 运行中/排队中可忽略
      }
    }
  } catch (e) {
    // 网络错误时忽略，下次重试
  }
}

export function getGenerationState(): GenerationState {
  return state;
}

export function subscribe(listener: Listener) {
  listeners.add(listener);
  return () => listeners.delete(listener);
}

export const generationManager = {
  getState: getGenerationState,
  subscribe,
  addPending,
  removePending,
  createTask: createGenerationTask,
  pollOnce,
  updateResultWork,
};


